﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Diagnostics.CodeAnalysis;

using Fuse8.DomainFramework.Domain;
using Fuse8.DomainFramework.Common;

namespace Fuse8.DomainFramework.BusinessService
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public abstract class BaseQueryLibrary<TEntity, TKey> 
        where TEntity : class, IEntityObject<TKey>, new()
        where TKey : IComparable<TKey>, IEquatable<TKey> 
    {
        #region Fields

        private BusinessServiceFacade<TEntity, TKey> _service = new BusinessServiceFacade<TEntity, TKey>();

        #endregion

        #region Properties

        /// <summary>
        /// 
        /// </summary>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "Uses non-compiled linq expression")]
        public virtual Expression<Func<TEntity, bool>> SlicerExpression { get; protected set; }

        /// <summary>
        /// 
        /// </summary>
        public bool HasSlicerExpression
        {
            get
            {
                return SlicerExpression != null;
            }
        } 

        #endregion

        #region Methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression"></param>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "Uses non-compiled linq expression")]
        public void AddSlicerExpression(Expression<Func<TEntity, bool>> expression)
        {
            if (SlicerExpression == null)
            {
                // set expression
                SlicerExpression = expression;
            }
            else
            {
                if (expression != null)
                {
                    // combine expressions
                    SlicerExpression = CombineExpressions(expression);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void RemoveSlicerExpression()
        {
            if (SlicerExpression != null)
            {
                SlicerExpression = null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerable<TEntity> FindAll()
        {
            return HasSlicerExpression ?
                _service.Find(SlicerExpression) :
                _service.FindAll();
        }

        /// <summary>
        /// 
        /// </summary>        
        /// <param name="id"></param>
        /// <returns></returns>
        public TEntity FindOne(TKey id)
        {
            return _service.FindOne(id);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "Uses non-compiled linq expression")]
        public virtual TEntity FindOne(Expression<Func<TEntity, bool>> expression)
        {
            return HasSlicerExpression ? 
                _service.FindOne(CombineExpressions(expression)) :
                _service.FindOne(expression);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "Uses non-compiled linq expression")]
        public virtual IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> expression)
        {
            return HasSlicerExpression ? 
                _service.Find(CombineExpressions(expression)) :
                _service.Find(expression);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "Uses non-compiled linq expression for making them combined")]
        protected Expression<Func<TEntity, bool>> CombineExpressions(Expression<Func<TEntity, bool>> expression)
        {
            Guard.ArgumentNotNull(expression, "expression");

            return SlicerExpression.And(expression);
        } 

        #endregion
    }
}
